#include <jni.h>
#include <string>
#include "native-lib.h"

/****************************************************
* 函数说明: get_framelen 获取报文长度
*
* 参数说明:  buf    -- 报文内容
****************************************************/
int get_framelen (unsigned char *buf)
{
    return get_datalen (buf) + 8;
}

/****************************************************
* 函数说明: get_datalen 获取数据域长度
*
* 参数说明:  buf    -- 报文内容
****************************************************/
int get_datalen (unsigned char *buf)
{
    int datalen = 0;

    datalen = buf[GW376_DATALEN_POS] | (buf[GW376_DATALEN_POS + 1] << 8);
    datalen = datalen >> 2;
    return datalen;
}

/****************************************************
* 函数说明: Calc_Crc 计算校验和
*
* 参数说明:  p -- 指向报文控制域的指针
*            len -- 从控制域字节到校验和之前一字节的报文长度
*
* 返回值: 累加校验和
****************************************************/
unsigned char Calc_Crc (int len, unsigned char *p)
{
    unsigned char crc = 0;
    int i = 0;

    for (i = 0; i<len; i++)
        crc = crc + p[i];

    return (crc);
}

/****************************************************
* 函数说明: get_ctrlcode 根据afn获取控制域
*
* 参数说明:  afn -- 应用层功能码
*
* 返回值: 控制域
****************************************************/
unsigned char get_ctrlcode (unsigned char afn)
{
    unsigned char ctrlcode = 0;

    switch (afn) {
        case AFN_RESET:
            ctrlcode = 0x01;
            break;
        case AFN_SETPARA:
            ctrlcode = 0x0A;
            break;
        case AFN_CTRL:
            ctrlcode = 0x0A;
            break;
        case AFN_ASKTERMCONFIG:
            ctrlcode = 0x00;
            break;
        case AFN_ASKPARA:
        case AFN_ASKONEDATA:
        case AFN_ASKTWODATA:
            ctrlcode = 0x0B;
            break;
        default: break;
    }

    ctrlcode |= GDW_CTRLCODE_DIR;	// DIR=0表示由主站下发的报文
    ctrlcode |= GDW_CTRLCODE_PRM;	// PRM=1表示报文来自启动站
    ctrlcode &= ~GDW_CTRLCODE_FCV;	// FCV无效

    return ctrlcode;
}

/****************************************************
* 函数说明: make_single_pn 转换测量点号(单个测量点号)
*
* 参数说明:  mpNo -- 测量点号
*
* 返回值: 报文中使用的测量点号
****************************************************/
unsigned short make_single_pn (int mpNo)
{
    unsigned short pn = 0;
    unsigned char DA2 = 0, DA1 = 0;

    if (mpNo <= 0) return 0;

    DA2 = ((mpNo - 1) / 8) + 1;
    DA1 = 1 << ((mpNo - 1) % 8);

    pn = (DA2 << 8) | DA1;

    return pn;
}

/****************************************************
* 函数说明: JByteArrayToChars转换
*
* 参数说明： byteArray
*
* 返回值: chars
****************************************************/
char* ConvertJByteArrayToChars(JNIEnv *env, jbyteArray byteArray){
    char *chars = NULL;
    jbyte *bytes;
    bytes = env->GetByteArrayElements(byteArray, 0);
    int chars_len = env->GetArrayLength(byteArray);
    chars = new char[chars_len + 1];
    memset(chars, 0, chars_len + 1);
    memcpy(chars, bytes, chars_len);
    chars[chars_len] = 0;
    env->ReleaseByteArrayElements(byteArray, bytes, 0);
    return chars;
}

jstring ConvertCharToJstring(JNIEnv *env, const char* str){
    //定义Java String类
    jclass strClass = (env) -> FindClass("java/lang/String");
    jmethodID ctorID = (env) -> GetMethodID(strClass, "<init>", "([BLjava/lang/String;)V");
    //建立byte数组
    jbyteArray bytes = (env) -> NewByteArray((jsize)strlen(str));
    //将char*转换为byte数组
    (env) -> SetByteArrayRegion(bytes, 0, (jsize)strlen(str), (jbyte*) str);
    //设置String，保存语言类型
    jstring encoding = (env) -> NewStringUTF("UTF-8");
    return (jstring)(env) -> NewObject(strClass, ctorID, bytes, encoding);
}

/////////////////////////////////////////////////////////
//////发送部分
/////////////////////////////////////////////////////////
//发送的报文
static unsigned char sendframe[512];
// 发送的报文长度
static int sendframelen = 0;

/****************************************************
* 函数说明: make_send_376_frame 组装376报文
*
* 参数说明：termaddr -- 4字节终端地址
*           A3       -- 主站地址
*           mpNo     -- 测量点号
*           afn      -- 应用层功能码
*           fn       -- 信息点标识
*           databuf  -- 数据域内容
*           datalen  -- 数据域长度
*           buf      -- 返回的报文内容
*           buflen   -- 返回的报文长度
****************************************************/
void make_send_376_frame (unsigned char *termaddr, unsigned char A3, int mpNo,
                          unsigned char afn, unsigned short fn,
                          unsigned char *databuf, int datalen,
                          unsigned char *buf, int *buflen)
{
    unsigned char  DT1 = 0, DT2 = 0, seq = 0, *p, pwd[16];
    unsigned short pn = 0, len = 0, len1 = 0;
    int pos = 0;

    memset (pwd, 0, sizeof (pwd));
    pos = 0;
    p = buf;

    p[pos++] = GW376_HEAD_68H;
    pos += 4;	// 跳过长度
    p[pos++] = GW376_HEAD_68H;

    p[pos++] = get_ctrlcode(afn);    // 功能码

    p[pos++] = termaddr[2];	 // 行政区域划码低字节
    p[pos++] = termaddr[3];	 // 行政区域划码高字节
    p[pos++] = termaddr[0];	 // 终端地址低字节
    p[pos++] = termaddr[1];	 // 终端地址高字节

    A3 = (A3 << 1) & 0xFE;     // 0xFE 标识组地址标志为0
    p[pos++] = A3;

    p[pos++] = afn;

    // 无时间标签  单帧  需要回复
    seq = GDW_SEQTPV_NONE | GDW_SEQFIRFIN_SINGLE | GDW_SEQCON_NEED;
    p[pos++] = seq;

    pn = make_single_pn (mpNo);
    p[pos++] = pn & 0xFF;			// DA1
    p[pos++] = (pn >> 8) & 0xFF;	// DA2

    DT1 = 1 << (((fn - 1) % 8));
    DT2 = (fn - 1) / 8;
    p[pos++] = DT1;	// DT1
    p[pos++] = DT2;	// DT2

    // 复制数据域到报文中，即使没有数据，datalen是0，也不影响
    memcpy (&p[pos], databuf, datalen);
    pos += datalen;

    // 根据AFN判断是否添加附加信息域
/*    if (((para->sendto.afn == AFN_RESET ||
        para->sendto.afn == AFN_SETPARA ||
        para->sendto.afn == AFN_CTRL) && para->sendto.askOrSetFlag == TO_SET) ||	// 确实发送的是设置数据
        para->sendto.afn == AFN_RESET) {
        memcpy (&p[pos], para->prot376.pw, 16);
        pos += 16;
    }*/
    if (afn == AFN_CTRL || afn == AFN_RESET) {
        memcpy (&p[pos], pwd, 16);
        pos += 16;
    }

    len = pos - GW376_CTRL_POS;
    len1 = (len << 2);
    p[1] = (unsigned char)(len1 & 0x00FC);
    p[1] |= GDW_LINKLEN_LOW2BIT;
    p[2] = (unsigned char)((len1 >> 8) & 0x00FF);
    p[3] = p[1];
    p[4] = p[2];

    p[pos] = Calc_Crc (pos - GW376_CTRL_POS, &p[GW376_CTRL_POS]);
    pos += 1;
    p[pos++] = GW376_TAIL_16H;

    *buflen = pos;
}

/****************************************************
* 函数说明: ctrl_fn003_send 控制换相
*
* 参数说明： mpNo      -- 测量点号
*           fromphase -- 源相位,    1: A相，2: B相，3: C相
*           tophase   -- 目标相位,  1: A相，2: B相，3: C相
*
* 返回值: 报文
****************************************************/
unsigned char *ctrl_fn003_send (unsigned char *termaddr, unsigned char A3,
                                int mpNo, unsigned char fromphase, unsigned char tophase)
{
    int datalen = 0;
    unsigned char afn = 0, databuf[32];
    unsigned short fn = 0;

    memset (sendframe, 0, sizeof (sendframe));
    memset (databuf, 0, sizeof (databuf));

    afn = AFN_CTRL;
    fn  = 3;

    databuf[0] = ((fromphase << 4) & 0xF0) | (tophase & 0x0F);
    datalen = 1;

    make_send_376_frame (termaddr, A3, mpNo, afn, fn,
                         databuf, datalen, sendframe, &sendframelen);

    return sendframe;
}


/****************************************************
* 函数说明: askOneData_fn15_send 换相开关在线状态
*
* 参数说明：
*
* 返回值： 报文
****************************************************/
unsigned char *askOneData_fn15_send (unsigned char *termaddr, unsigned char A3)
{
    int datalen = 0;
    unsigned char afn = 0, databuf[32];
    unsigned short fn = 0;

    memset (sendframe, 0, sizeof (sendframe));
    memset (databuf, 0, sizeof (databuf));

    afn = AFN_ASKONEDATA;
    fn = 15;
    datalen = 0;

    make_send_376_frame (termaddr, A3, 0, afn, fn,
                         databuf, datalen, sendframe, &sendframelen);

    return sendframe;
}

/****************************************************
* 函数说明: askOneData_fn179_send 电压不平衡度和电流不平衡度
*
* 参数说明：
*
* 返回值： 报文
****************************************************/
unsigned char *askOneData_fn179_send (unsigned char *termaddr, unsigned char A3)
{
    int datalen = 0;
    unsigned char afn = 0, databuf[32];
    unsigned short fn = 0;

    memset (sendframe, 0, sizeof (sendframe));
    memset (databuf, 0, sizeof (databuf));

    afn = AFN_ASKONEDATA;
    fn = 179;
    datalen = 0;

    make_send_376_frame (termaddr, A3, 0, afn, fn,
                         databuf, datalen, sendframe, &sendframelen);

    return sendframe;
}

/****************************************************
* 函数说明: askOneData_fn181_send 换相开关(三相电压、负荷电流、负荷电压、负荷功率因数、负荷电流、电压不平衡度)
*
* 参数说明：mpNo      -- 测量点号
*
* 返回值： 报文
****************************************************/
unsigned char *askOneData_fn181_send (unsigned char *termaddr, unsigned char A3, int mpNo)
{
    int datalen = 0;
    unsigned char afn = 0, databuf[32];
    unsigned short fn = 0;

    memset (sendframe, 0, sizeof (sendframe));
    memset (databuf, 0, sizeof (databuf));

    afn = AFN_ASKONEDATA;
    fn = 181;
    datalen = 0;

    make_send_376_frame (termaddr, A3, mpNo, afn, fn,
                         databuf, datalen, sendframe, &sendframelen);

    return sendframe;
}

/****************************************************
* 函数说明: askTwoData_fn239_send 日冻结换相开关总次数
*
* 参数说明：mpNo      -- 测量点号
*           year      -- 年(2018)
*           month     -- 月
*           day       -- 日
*
* 返回值：报文
****************************************************/
unsigned char *askTwoData_fn239_send (unsigned char *termaddr, unsigned char A3, int mpNo,
                                      int year, unsigned char month, unsigned char day)
{
    int datalen = 0, pos = 0;
    unsigned char afn = 0,  databuf[32];
    unsigned short fn = 0;

    memset (sendframe, 0, sizeof (sendframe));
    memset (databuf, 0, sizeof (databuf));

    afn = AFN_ASKTWODATA;
    fn = 239;

    databuf[pos++] = BIN_TO_BCD (day);
    databuf[pos++] = BIN_TO_BCD (month);
    databuf[pos++] = BIN_TO_BCD (year%100);
    datalen = pos;

    make_send_376_frame (termaddr, A3, mpNo, afn, fn,
                         databuf, datalen, sendframe, &sendframelen);

    return sendframe;
}

/****************************************************
* 函数说明: askTwoData_fn240_send 日冻结换相开关总次数
*
* 参数说明：mpNo      -- 测量点号
*           year      -- 年(2018)
*           month     -- 月
*
* 返回值: 报文
****************************************************/
unsigned char *askTwoData_fn240_send (unsigned char *termaddr, unsigned char A3,
                                      int mpNo, int year, unsigned char month)
{
    int datalen = 0, pos = 0;
    unsigned char afn = 0, databuf[32];
    unsigned short fn = 0;

    memset (sendframe, 0, sizeof (sendframe));
    memset (databuf, 0, sizeof (databuf));

    afn = AFN_ASKTWODATA;
    fn = 240;

    databuf[pos++] = BIN_TO_BCD (month);
    databuf[pos++] = BIN_TO_BCD (year%100);
    datalen = pos;

    make_send_376_frame (termaddr, A3, mpNo, afn, fn,
                         databuf, datalen, sendframe, &sendframelen);

    return sendframe;
}

extern "C"
JNIEXPORT jbyteArray JNICALL
Java_ke_phasechange_gw376_GW376Send_ctrlFn003Send(JNIEnv *env, jobject instance, jbyteArray termaddr, jbyte A3, jint mpNo,
                                              jbyte fromphase, jbyte tophase) {

    unsigned char *address = (unsigned char *) ConvertJByteArrayToChars(env, termaddr);

    unsigned char *result = ctrl_fn003_send(address, A3, mpNo, fromphase, tophase);
    int length = get_framelen(result);

    jbyte *jb = (jbyte*)result;
    jbyteArray jarray = env->NewByteArray(length);
    env -> SetByteArrayRegion(jarray, 0, length, jb);

    return jarray;
}

extern "C"
JNIEXPORT jbyteArray JNICALL
Java_ke_phasechange_gw376_GW376Send_askOneDataFn179Send(JNIEnv *env, jobject instance,
                                                    jbyteArray termaddr_, jbyte A3) {
    unsigned char *address = (unsigned char *) ConvertJByteArrayToChars(env, termaddr_);

    unsigned char *result = askOneData_fn179_send(address, A3);

    int length = get_framelen(result);

    jbyte *jb = (jbyte*)result;
    jbyteArray jarray = env->NewByteArray(length);
    env -> SetByteArrayRegion(jarray, 0, length, jb);

    return jarray;
}

extern "C"
JNIEXPORT jbyteArray JNICALL
Java_ke_phasechange_gw376_GW376Send_askOneDataFn181Send(JNIEnv *env, jobject instance,
                                                    jbyteArray termaddr_, jbyte A3, jint mpNo) {
    unsigned char *address = (unsigned char *) ConvertJByteArrayToChars(env, termaddr_);

    unsigned char *result = askOneData_fn181_send(address, A3, mpNo);

    int length = get_framelen(result);

    jbyte *jb = (jbyte*)result;
    jbyteArray jarray = env->NewByteArray(length);
    env -> SetByteArrayRegion(jarray, 0, length, jb);

    return jarray;
}

extern "C"
JNIEXPORT jbyteArray JNICALL
Java_ke_phasechange_gw376_GW376Send_askTwoDataFn239Send(JNIEnv *env, jobject instance,
                                                    jbyteArray termaddr_, jbyte A3, jint mpNo,
                                                    jint year, jbyte month, jbyte day) {
    unsigned char *address = (unsigned char *) ConvertJByteArrayToChars(env, termaddr_);

    unsigned char *result = askTwoData_fn239_send(address, A3, mpNo, year, month, day);

    int length = get_framelen(result);

    jbyte *jb = (jbyte*)result;
    jbyteArray jarray = env->NewByteArray(length);
    env -> SetByteArrayRegion(jarray, 0, length, jb);

    return jarray;
}

extern "C"
JNIEXPORT jbyteArray JNICALL
Java_ke_phasechange_gw376_GW376Send_askTwoDataFn240Send(JNIEnv *env, jobject instance,
                                                    jbyteArray termaddr_, jbyte A3, jint mpNo,
                                                    jint year, jbyte month) {
    unsigned char *address = (unsigned char *) ConvertJByteArrayToChars(env, termaddr_);

    unsigned char *result = askTwoData_fn240_send(address, A3, mpNo, year, month);

    int length = get_framelen(result);

    jbyte *jb = (jbyte*)result;
    jbyteArray jarray = env->NewByteArray(length);
    env -> SetByteArrayRegion(jarray, 0, length, jb);

    return jarray;
}

extern "C"
JNIEXPORT jbyteArray JNICALL
Java_ke_phasechange_gw376_GW376Send_askOneDataFn15Send(JNIEnv *env, jclass type,
                                                       jbyteArray termaddr_, jbyte A3) {

    unsigned char *address = (unsigned char *) ConvertJByteArrayToChars(env, termaddr_);

    unsigned char *result = askOneData_fn15_send(address, A3);

    int length = get_framelen(result);

    jbyte *jb = (jbyte*)result;
    jbyteArray jarray = env->NewByteArray(length);
    env -> SetByteArrayRegion(jarray, 0, length, jb);

    return jarray;
}

//////////////////////////////////////////////////////////////////////////////////////
///接收
/// //////////////////////////////////////////////////////////////////////////////////

static unsigned char UCHAR_BITS[] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};

// 接收的一帧完整报文
static unsigned char recvframe[512];
// 接收的一帧完整报文的长度
static int recvframelen = 0;

// 解析数据的返回字符串
static char retbuf[1024];

/****************************************************
* 函数说明: data_is_valid 检查数据是否有效，全0xEE为无效
*
* 参数说明:  buf    -- 数据内容
*            len    -- 数据长度
*
* 返回值: 1 -- 数据有效，0 -- 数据无效
****************************************************/
unsigned char data_is_valid (unsigned char *buf, int len)
{
    for (int i = 0; i < len; i++) {
        if (buf[i] != 0xEE) return 1;
    }

    return 0;
}

unsigned char get_A5_data (unsigned char *p, float *val, int *len)
{
    int pos = 0, i = 0;
    float fval = 0.0f;
    unsigned char b1 = 0, b2 = 0, s = 0;
    *val = 0.0f;
    if (p == NULL) return 0;

    b1 = BCD_TO_BIN (p[pos]);
    pos += 1;
    b2 = BCD_TO_BIN (p[pos] & 0x7F);
    pos += 1;
    s = (p[1] >> 7) & 0x01;

    fval = (float)(b1 / 10.0 + b2*10.0);
    if (s) {
        fval = (float)((-1.0)*fval);
    }

    *val = fval;
    *len = pos;
    
    // 检测数据是否无效
    if (data_is_valid(p, *len) == 0) {
        *val = 0.0f;
    }

    return 1;
}

unsigned char get_A7_data (unsigned char *p, float *val, int *len)
{
    int pos = 0, i = 0;
    float fval = 0.0f;
    unsigned char b1 = 0, b2 = 0;
    *val = 0.0f;
    if (p == NULL) return 0;

    b1 = BCD_TO_BIN (p[pos]);
    pos += 1;
    b2 = BCD_TO_BIN (p[pos]);
    pos += 1;

    fval = (float)(b1 / 10.0 + b2*10.0);
    *val = fval;
    *len = pos;
    
    // 检测数据是否无效
    if (data_is_valid(p, *len) == 0) {
        *val = 0.0f;
    }

    return 1;
}

unsigned char get_A15_data (unsigned char *p, T_SYSTEMTIME *st, int *len)
{
    int pos = 0, i = 0;

    if (p == NULL) return 0;
    if (st == NULL) return 0;

    memset (st, 0, sizeof (T_SYSTEMTIME));

    st->minute = BCD_TO_BIN (p[pos]);	pos += 1;
    st->hour   = BCD_TO_BIN (p[pos]);	pos += 1;
    st->day    = BCD_TO_BIN (p[pos]);	pos += 1;
    st->month  = BCD_TO_BIN (p[pos]);	pos += 1;
    st->year   = BCD_TO_BIN (p[pos]);	pos += 1;
    *len = pos;
    
    // 检测数据是否无效
    if (data_is_valid(p, *len) == 0) {
        memset(st, 0, sizeof(T_SYSTEMTIME));
    }

    return 1;
}


unsigned char get_A20_data (unsigned char *p, T_SYSTEMTIME *st, int *len)
{
    int pos = 0, i = 0;

    if (p == NULL) return 0;
    memset (st, 0, sizeof (T_SYSTEMTIME));

    st->day   = BCD_TO_BIN (p[pos]);	pos += 1;
    st->month = BCD_TO_BIN (p[pos]);	pos += 1;
    st->year  = BCD_TO_BIN (p[pos]);	pos += 1;
    *len = pos;
    
    // 检测数据是否无效
    if (data_is_valid(p, *len) == 0) {
        memset(st, 0, sizeof(T_SYSTEMTIME));
    }

    return 1;
}

unsigned char get_A21_data (unsigned char *p, T_SYSTEMTIME *st, int *len)
{
    int pos = 0, i = 0;

    if (p == NULL) return 0;
    memset (st, 0, sizeof (T_SYSTEMTIME));

    st->month = BCD_TO_BIN (p[pos]);	pos += 1;
    st->year  = BCD_TO_BIN (p[pos]);	pos += 1;
    *len = pos;
    
    // 检测数据是否无效
    if (data_is_valid(p, *len) == 0) {
        memset(st, 0, sizeof(T_SYSTEMTIME));
    }

    return 1;
}

unsigned char get_A25_data (unsigned char *p, float *val, int *len)
{
    float fval = 0.0f;
    unsigned char b1 = 0, b2 = 0, b3 = 0, s = 0;
    *val = 0.0f;
    if (p == NULL) return 0;

    b1 = BCD_TO_BIN (p[0]);
    b2 = BCD_TO_BIN (p[1]);
    b3 = BCD_TO_BIN (p[2] & 0x7F);
    s = (p[2] >> 7) & 0x01;

    fval = (float)((float)b3*10.0 + (float)b2 / 10.0 + (float)b1 / 1000.0);
    if (s) {	// 最高位是1，代表负值
        fval = (-1.0f) * fval;
    }
    *val = fval;
    *len = 3;
    
    // 检测数据是否无效
    if (data_is_valid(p, *len) == 0) {
        *val = 0.0f;
    }

    return 1;
}

int get_Td_d_value (unsigned char *p, T_SYSTEMTIME *st, int *len)
{
    int pos = 0, eleLen = 0;
    if (p == NULL) return 0;
    if (st == NULL) return 0;

    get_A20_data (p, st, &eleLen);
    pos += eleLen;

    *len = pos;

    return 1;
}

int get_Td_m_value (unsigned char *p, T_SYSTEMTIME *st, int *len)
{
    int pos = 0, eleLen = 0;
    if (p == NULL) return 0;
    if (st == NULL) return 0;

    get_A21_data (p, st, &eleLen);
    pos += eleLen;
    *len = pos;

    return 1;
}

unsigned short get_SingleFN (int dt1, int dt2)
{
    int i = 0;
    unsigned short fn = 0;

    for (i = 0; i < 8; i++) {
        if (dt1 & UCHAR_BITS[i]) break;
    }
    if (i == 8)  fn = 0;
    else         fn = dt2 * 8 + (i + 1);

    return fn;
}



/****************************************************
* 函数说明: get_afn_fn 从报文中获取AFN和FN
*
* 参数说明:  frame    -- 报文内容
*            afn    -- 应用层功能码
*            fn     -- 信息类型
*
* 返回值: 累加校验和
****************************************************/
void get_afn_fn (unsigned char *frame, unsigned char *afn, unsigned short *fn)
{
    unsigned char dt1 = 0, dt2 = 0;

    *afn = frame[AFN_POS];

    dt1 = frame[FIRST_FN_POS];
    dt2 = frame[FIRST_FN_POS + 1];
    *fn = get_SingleFN (dt1, dt2);
}


/****************************************************
* 函数说明: askOneData_fn15_recv 解析一类数据 换相开关在线状态
*
* 参数说明:  frame    -- 报文内容
*
* 返回值: 解析出来的数据字符串
****************************************************/
char *askOneData_fn15_recv (unsigned char *frame)
{
    int i = 0, pos = 0, offset = 0;
    unsigned int type = 0;
    unsigned char *p = NULL, afn = 0, flag = 0, data[4];
    unsigned short fn = 0;
    char buf[256];

    memset (buf, 0, sizeof(buf));
    memset (data, 0, sizeof(data));

    get_afn_fn (frame, &afn, &fn);
    type = (afn << 16 | fn);         // 类型

    snprintf (retbuf, sizeof (retbuf),"{\"type\":%d,\"data\":[", type);
    
    p = frame + DATA_START_POS;   // 指向数据域第一个字节
    memcpy (data, p, 4);
    for (i = 0; i < 32; i++) {
		pos = i / 8;
		offset = i % 8;
		flag = ((data[pos] >> offset) & 0x01);
		if (flag) {     // 在线
            snprintf(buf, sizeof(buf), "{\"kg\":%d,\"status\":%d}", i + 1, 1);
        }
		else  {     // 不在线
            snprintf(buf, sizeof(buf), "{\"kg\":%d,\"status\":%d}", i + 1, 0);
        }
        strcat (retbuf, buf);
        if (i != (32-1)) strcat(retbuf, ",");
		
	}

    snprintf(buf, sizeof(buf), "%s", "]}");
    strcat (retbuf, buf);
    
    return retbuf;
}

/****************************************************
* 函数说明: askOneData_fn179_recv 解析一类数据 电压不平衡度和电流不平衡度
*
* 参数说明:  frame    -- 报文内容
*
* 返回值: 解析出来的数据字符串
****************************************************/
char *askOneData_fn179_recv (unsigned char *frame)
{
    int len = 0, framelen = 0;
    float voltageub = 0.0f, currentub = 0.0f;
    unsigned int type = 0;
    unsigned char *p = NULL, afn = 0;
    unsigned short fn = 0;
    T_SYSTEMTIME st;

    memset (&st, 0, sizeof (st));

    get_afn_fn (frame, &afn, &fn);
    type = (afn << 16 | fn);         // 类型

    p = frame + DATA_START_POS;   // 指向数据域第一个字节

    get_A15_data (p, &st, &len);         p += len;
    st.year += 2000;
    get_A7_data (p, &voltageub, &len);   p += len;
    get_A7_data (p, &currentub, &len);   p += len;

    // 字符转内容：类型，日期时间，电压不平衡度，电流不平衡度
    snprintf (retbuf, sizeof (retbuf),
              "{\"type\":%d,\"data\":{\"time\":\"%d-%d-%d %d:%d:%d\",\"votageunbalance\":%.1f,\"currentunbalance\":%.1f}}",
              type, st.year, st.month, st.day, st.hour, st.minute, st.second,
              voltageub, currentub);

    return retbuf;
}

/****************************************************
* 函数说明: askOneData_fn181_recv 解析一类数据   换相开关(三相电压、负荷电流、负荷电压、负荷功率因数、负荷电流、电压不平衡度)
*
* 参数说明:  frame    -- 报文内容
*
* 返回值: 解析的数据字符串
****************************************************/
char *askOneData_fn181_recv (unsigned char *frame)
{
    int len = 0;
    unsigned char *p = NULL, afn = 0, curphase = 0;
    T_SYSTEMTIME st;
    unsigned int type = 0;
    unsigned short fn = 0;
    float curVolA, curVolB, curVolC, curLoadVol, curLoadCurrent;
    float curLoadPowerFactor, curLoadLekageCurrent, curVolUnbalance;

    curVolA = curVolB = curVolC = curLoadVol = curLoadCurrent = 0.0f;
    curLoadPowerFactor = curLoadLekageCurrent = curVolUnbalance = 0.0f;

    memset (&st, 0, sizeof (st));

    get_afn_fn (frame, &afn, &fn);
    type = (afn << 16 | fn);         // 类型

    p = frame + DATA_START_POS;   // 指向数据域第一个字节

    get_A15_data (p, &st, &len);    p += len;
    st.year += 2000;

    get_A7_data (p, &curVolA, &len);   p += len;
    get_A7_data (p, &curVolB, &len);   p += len;
    get_A7_data (p, &curVolC, &len);   p += len;
    get_A7_data (p, &curLoadVol, &len);   p += len;
    get_A25_data (p, &curLoadCurrent, &len); p += len;
    get_A5_data (p, &curLoadPowerFactor, &len); p += len;
    get_A25_data (p, &curLoadLekageCurrent, &len); p += len;
    get_A7_data (p, &curVolUnbalance, &len); p += len;
    curphase = p[0];    p += 1;     // 1--A  2--B  3--C

    snprintf (retbuf, sizeof (retbuf),
              "{\"type\":%d,\"data\":{\"time\":\"%d-%d-%d %d:%d\",\"curVolA\":%.1f,\"curVolB\":%.1f,\"curVolC\":%.1f,\"curLoadVol\":%.1f,\"curLoadCurrent\":%.3f,\"curLoadPowerFactor\":%.1f,\"curLoadLekageCurrent\":%.3f,\"curVolUnbalance\":%.1f,\"curPhase\":%d}}",
              type, st.year, st.month, st.day, st.hour, st.minute,
              curVolA, curVolB, curVolC,
              curLoadVol, curLoadCurrent,
              curLoadPowerFactor, curLoadLekageCurrent, curVolUnbalance, curphase);

    return retbuf;
}

/****************************************************
* 函数说明: askTwoData_fn239_recv 解析二类数据 日冻结换相开关动作次数
*
* 参数说明:  frame    -- 报文内容
*
* 返回值： 解析数据的字符串
****************************************************/
char *askTwoData_fn239_recv (unsigned char *frame)
{
    int len = 0;
    unsigned char *p = NULL, afn = 0;
    T_SYSTEMTIME st;
    unsigned int type = 0, times = 0;
    unsigned short fn = 0;

    memset (&st, 0, sizeof (st));

    get_afn_fn (frame, &afn, &fn);
    type = (afn << 16 | fn);         // 类型

    p = frame + DATA_START_POS;   // 指向数据域第一个字节

    get_Td_d_value (p, &st, &len);      p += len;
    st.year += 2000;

    times = BCD_TO_BIN (p[0]) + BCD_TO_BIN (p[1]) * 100 +
            BCD_TO_BIN (p[2]) * 10000 + BCD_TO_BIN (p[3]) * 1000000;

    snprintf (retbuf, sizeof (retbuf), "{\"type\":%d,\"data\":{\"time\":\"%d-%d-%d\",\"times\":%d}}",
              type, st.year, st.month, st.day, times);

    return retbuf;
}

/****************************************************
* 函数说明: askTwoData_fn240_recv 解析二类数据 月冻结换相开关动作次数
*
* 参数说明:  frame    -- 报文内容
*
* 返回值：解析数据的字符串
****************************************************/
char *askTwoData_fn240_recv (unsigned char *frame)
{
    int len = 0;
    unsigned char *p = NULL, afn = 0;
    T_SYSTEMTIME st;
    unsigned short fn = 0;
    unsigned int type = 0, times = 0;

    memset (&st, 0, sizeof (st));

    get_afn_fn (frame, &afn, &fn);
    type = (afn << 16 | fn);         // 类型

    p = frame + DATA_START_POS;   // 指向数据域第一个字节

    get_Td_m_value (p, &st, &len);      p += len;
    st.year += 2000;

    if (p[0] == 0xEE && p[1] == 0xEE && p[2] == 0xEE && p[3] == 0xEE) {
        times = 0;
    }
    else {
        times = BCD_TO_BIN (p[0]) + BCD_TO_BIN (p[1]) * 100 +
                BCD_TO_BIN (p[2]) * 10000 + BCD_TO_BIN (p[3]) * 1000000;
    }

    snprintf (retbuf, sizeof (retbuf), "{\"type\":%d,\"data\":{\"time\":\"%d-%d\",\"times\":%d}}",
              type, st.year, st.month, times);

    return retbuf;
}

/****************************************************
* 函数说明: sure_deny_recv 确认否认
*
* 参数说明:  frame    -- 报文内容
*
* 返回值：确认否认的字符串
****************************************************/
char *sure_deny_recv (unsigned char *frame)
{
    unsigned int type = 0;
    unsigned short fn = 0;
    unsigned char afn = 0;

    get_afn_fn (frame, &afn, &fn);
    type = afn << 16 | fn;

    if (afn == AFN_SUREDENY && fn == 1)
        snprintf(retbuf, sizeof(retbuf), "{\"type\":%d, \"data\":{\"suredeny\":\"ok\"}}", type);
    else
        snprintf (retbuf, sizeof (retbuf), "{\"type\":%d, \"data\":{\"suredeny\":\"no\"}}", type);

    return retbuf;
}

/****************************************************
* 函数说明: is_frame_complete 检查报文是否是完整的一帧报文
*
* 参数说明:  frame -- 报文内容
*
* 返回值： 1 -- 完整报文，0 -- 不完整报文
****************************************************/
unsigned char is_frame_complete (unsigned char *frame)
{
    int framelen = 0;
    unsigned char *p = frame;

    if (p[GW376_FIRST_68H_POS] != GW376_HEAD_68H ||
        p[GW376_SECOND_68H_POS] != GW376_HEAD_68H) return 0;

    framelen = get_framelen (frame);
    if (p[framelen - 1] != GW376_TAIL_16H) return 0;

    return 1;
}

/****************************************************
* 函数说明: parse_recv_frame 解析接收的报文
*
* 参数说明:  frame    -- 报文内容
*
* 返回值：解析的数据字符串
****************************************************/
char *parse_recv_frame (unsigned char *frame)
{
    unsigned char afn = 0;
    unsigned short fn = 0;
    char *ret = NULL;

    memset (retbuf, 0, sizeof (retbuf));
    if (is_frame_complete (frame) == 0) return NULL;

    get_afn_fn (frame, &afn, &fn);

    if (afn == AFN_SUREDENY) {      // 确认和否认
        ret = sure_deny_recv (frame);
    }
    else if (afn == AFN_ASKONEDATA) {
        if (fn == 15) {
            ret = askOneData_fn15_recv (frame);
        }
        else if (fn == 179) {
            ret = askOneData_fn179_recv (frame);
        }
        else if (fn == 181) {
            ret = askOneData_fn181_recv (frame);
        }
    }
    else if (afn == AFN_ASKTWODATA) {
        if (fn == 239) {
            ret = askTwoData_fn239_recv (frame);
        }
        else if (fn == 240) {
            ret = askTwoData_fn240_recv (frame);
        }
    }
    else {
        ret = NULL;
    }

    return ret;
}

extern "C"
JNIEXPORT jstring JNICALL
Java_ke_phasechange_gw376_GW376Receive_parseRecvFrame(JNIEnv *env, jclass type, jbyteArray frame_) {

    unsigned char *frame = (unsigned char *) ConvertJByteArrayToChars(env, frame_);

    char *result = parse_recv_frame(frame);

    if(result == NULL)
        return (jstring) "";

    jstring rtn = ConvertCharToJstring(env, result);

    return rtn;
}